package org.budo.support.jedis.util;

import java.lang.reflect.Method;

import org.budo.support.java.net.util.JavaNetUtil;
import org.budo.support.lang.util.ProcessUtil;
import org.budo.support.lang.util.ReflectUtil;

import lombok.extern.slf4j.Slf4j;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

/**
 * @author li
 * @version 1 (2015年3月27日 下午4:05:02)
 * @since Java7
 */
@Slf4j
public class JedisUtil {
    public static void tryLock(JedisPool jedisPool, String key, Runnable runnable, Number expireIn) {
        if (null == jedisPool) {
            log.error("#19 tryLock, jedisPool=" + jedisPool + ", key=" + key + ", runnable=" + runnable);
            return;
        }

        // 尝试拿锁 不会自动过期
        Jedis jedis = jedisPool.getResource();
        String value = runnable + ", ip=" + JavaNetUtil.getIpAddresses() + ", p=" + ProcessUtil.getCurrentProcessName();
        Long setnx = jedis.setnx(key, value); // 抢锁

        // 没拿到锁
        if (null == setnx || setnx < 1) {
            log.warn("#33 tryLock return, KEY=" + key + ", setnx=" + setnx);
            return;
        }

        // 拿到锁了
        try {
            jedis.expire(key, expireIn.intValue()); // 自动过期 防范程序死未释放了之类的

            runnable.run();
        } catch (Throwable e) {
            log.error("#182 tryLock error, e=" + e + ", key=" + key + ", runnable=" + runnable + ", expireIn=" + expireIn, e);
        } finally {
            jedis.del(key); // 完事后删除锁
            jedis.close();
        }
    }

    public static void closeQuietly(Jedis jedis) {
        try {
            if (null == jedis) {
                return;
            }

            jedis.quit();
            jedis.disconnect();
            jedis.close();

            jedis = null;
        } catch (Throwable e) {
            if (log.isDebugEnabled()) {
                log.debug("#26 close Jedis error, e=" + e, e);
            }
        }
    }

    public static void close(Jedis jedis) {
        try {
            if (null == jedis) {
                return;
            }

            jedis.quit();
            jedis.disconnect();
            jedis.close();

            jedis = null;
        } catch (Throwable e) {
            log.error("#26 close Jedis error, e=" + e, e);
        }
    }

    /**
     * 反射避免maven依赖
     */
    public static JedisPool budoJedisPool(String redisHost, Integer redisPort, String redisPassword) {
        Class targetType = ReflectUtil.classForName("org.budo.jedis.pool.factory.BudoJedisPoolFactory");
        Method method = ReflectUtil.getMethod(targetType, "budoJedisPool_1", new Class[] { String.class, Integer.class, String.class });
        return (JedisPool) ReflectUtil.invokeMethod(null, method, new Object[] { redisHost, redisPort, redisPassword });
    }
}